﻿using System;
using System.Collections.Generic;
using Company.Project.Domain.Base;
using Company.Project.Domain.MainModule.Interface;
using Company.Project.Domain.Model;
using Company.Project.Domain.Model.DTO;
using Company.Project.Infrastructure.Repository.Sqlserver.DataBaseFactory;
using Company.Project.Infrastructure.Repository.Sqlserver.RepositoriesBase;
using System.Linq;
using System.Threading.Tasks;
using Company.Project.Infrastructure.Common;
using Company.Project.Infrastructure.Common.Enums;
using Company.Utility;
using Microsoft.EntityFrameworkCore;

namespace Company.Project.Infrastructure.Repository.Sqlserver
{
    public class Project_Manager_BaseInfoRepository : RepositoryBase<Project_Manager_BaseInfo>, IProject_Manager_BaseInfoRepository
    {
        public Project_Manager_BaseInfoRepository(IDatabaseFactory databaseFactory)
            : base(databaseFactory)
        {

        }

        public async Task<Project_Manager_BaseInfo> GetLoginUser(ISpecification<Project_Manager_BaseInfo> specification)
        {
            var n = await (from a in dbset.Where(specification.SatisfiedBy())
                let Roles = (from b in DataContext.Project_Manager_Role.Where(x => x.MemberId == a.ID && !x.IsDeleted)
                    let Role = (from c in DataContext.Project_SYS_Role.Where(x => !x.IsDeleted && x.ID == b.RoleId)
                        let RoleActions = (from d in DataContext.Project_SYS_RoleAction.Where(x => x.RoleID == c.ID)
                            select new
                            {
                                ID = d.ID,
                                RoleID = d.RoleID,
                                ModuleID = d.ModuleID,
                                Weight = d.Weight
                            })
                        select new
                        {
                            ID = c.ID,
                            RoleName = c.RoleName,
                            Memo = c.Memo,
                            OrderID = c.OrderID,
                            IsDeleted = c.IsDeleted,
                            RoleActions = RoleActions
                        }
                    ).FirstOrDefault()
                    select new
                    {
                        ID = b.ID,
                        RoleId = b.RoleId,
                        MemberId = b.MemberId,
                        IsDeleted = b.IsDeleted,
                        CreateTime = b.CreateTime,
                        Role = Role
                    })
                select new
                {
                    ID = a.ID,
                    LoginName = a.LoginName,
                    PassWord = a.PassWord,
                    NickName = a.NickName,
                    State = a.State,
                    LastLoginIP = a.LastLoginIP,
                    LastLoginTime = a.LastLoginTime,
                    ThisLoginIP = a.ThisLoginIP,
                    ThisLoginTime = a.ThisLoginTime,
                    LoginNumber = a.LoginNumber,
                    CreateTime = a.CreateTime,
                    IsDeleted = a.IsDeleted,
                    Roles = Roles
                }).FirstOrDefaultAsync();
            var result = new Project_Manager_BaseInfo()
            {
                ID = n.ID,
                LoginName = n.LoginName,
                PassWord = n.PassWord,
                NickName = n.NickName,
                State = n.State,
                LastLoginIP = n.LastLoginIP,
                LastLoginTime = n.LastLoginTime,
                ThisLoginIP = n.ThisLoginIP,
                ThisLoginTime = n.ThisLoginTime,
                LoginNumber = n.LoginNumber,
                CreateTime = n.CreateTime,
                IsDeleted = n.IsDeleted,
                Roles = new List<Project_Manager_Role>()
            };
            n.Roles.ToList().ForEach(x =>
            {
                var sysrole = new Project_Manager_Role()
                {
                    ID = x.ID,
                    RoleId = x.RoleId,
                    MemberId = x.MemberId,
                    IsDeleted = x.IsDeleted,
                    CreateTime = x.CreateTime
                };
                sysrole.Role = new Project_SYS_Role()
                {
                    ID = x.Role.ID,
                    RoleName = x.Role.RoleName,
                    Memo = x.Role.Memo,
                    OrderID = x.Role.OrderID,
                    IsDeleted = x.Role.IsDeleted,
                    RoleActions = new List<Project_SYS_RoleAction>()
                };
                x.Role.RoleActions.ToList().ForEach(y =>
                {
                    sysrole.Role.RoleActions.Add(new Project_SYS_RoleAction()
                    {
                        ID = y.ID,
                        RoleID = y.RoleID,
                        ModuleID = y.ModuleID,
                        Weight = y.Weight
                    });
                });
                result.Roles.Add(sysrole);
            });
            return result;
        }

        public async Task<EntityList<BaseInfoDTO>> GetBaseInfoList(int page, int rows, ISpecification<Project_Manager_BaseInfo> specification, Dictionary<string, string> sort)
        {
            var query = (from a in dbset.Where(specification.SatisfiedBy()).Include(x => x.Roles).ThenInclude(x => x.BaseInfo)
                         select new BaseInfoDTO()
                         {
                             ID = a.ID,
                             LoginName = a.LoginName,
                             NickName = a.NickName,
                             State = a.State,
                             CreateTime = a.CreateTime,
                             MangerRole = a.Roles.Where(x => !x.IsDeleted).Select(x => x.Role.RoleName),
                             LastLoginTime = a.LastLoginTime,
                             LastLoginIP =a.LastLoginIP,
                             ThisLoginTime = a.ThisLoginTime,
                             ThisLoginIP = a.ThisLoginIP,
                             LoginNumber = a.LoginNumber
                         });
            var result =await FindAllAsyncAsQuery(DataSort(query, sort), page, rows);
            result.Data.ForEach(x =>
            {
                x.StateName = x.State.GetLocalizedDescription();
                x.MangerRoleName = string.Join(",", x.MangerRole);
                x.LastLoginTimeStr = x.LastLoginTime?.ToString("yyyy-MM-dd HH:mm:ss");
                x.ThisLoginTimeStr = x.ThisLoginTime?.ToString("yyyy-MM-dd HH:mm:ss");
            });
            return result;
        }

        public async Task<bool> ExistsRoleByRoleId(IEnumerable<Guid> ids)
        {
            return await (from a in DataContext.Project_SYS_Role.Where(x => !x.IsDeleted && ids.Contains(x.ID))
                join b in DataContext.Project_Manager_Role.Where(x => !x.IsDeleted) on a.ID equals b.RoleId
                join c in DataContext.Project_Manager_BaseInfo.Where(x => !x.IsDeleted) on b.MemberId equals c.ID
                select c.ID
                ).AnyAsync();
        }
    }
}